package cn.iocoder.yudao.module.system.service.studentdashboard;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.studentdashboard.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.examclass.ExamClassDO;
import cn.iocoder.yudao.module.system.dal.dataobject.examclass.ExamClassStudentDO;
import cn.iocoder.yudao.module.system.dal.dataobject.examscore.ExamScoreDO;
import cn.iocoder.yudao.module.system.dal.dataobject.examtest.ExamTestDO;
import cn.iocoder.yudao.module.system.dal.dataobject.goal.StudentMajorGroupGoalDO;
import cn.iocoder.yudao.module.system.dal.mysql.examclass.ExamClassMapper;
import cn.iocoder.yudao.module.system.dal.mysql.examclass.ExamClassStudentMapper;
import cn.iocoder.yudao.module.system.dal.mysql.examscore.ExamScoreMapper;
import cn.iocoder.yudao.module.system.dal.mysql.examtest.ExamTestMapper;
import cn.iocoder.yudao.module.system.dal.mysql.subjectscoredetail.SubjectScoreDetailMapper;
import cn.iocoder.yudao.module.system.dal.dataobject.subjectscoredetail.SubjectScoreDetailDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;

/**
 * 学生看板 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Slf4j
public class StudentDashboardServiceImpl implements StudentDashboardService {

    @Resource
    private ExamScoreMapper examScoreMapper;
    
    @Resource
    private ExamTestMapper examTestMapper;
    
    @Resource
    private ExamClassMapper examClassMapper;
    
    @Resource
    private ExamClassStudentMapper examClassStudentMapper;
    
    @Resource
    private SubjectScoreDetailMapper subjectScoreDetailMapper;
    
    @Resource
    private cn.iocoder.yudao.module.system.service.equivalentscorerank.EquivalentScoreRankService equivalentScoreRankService;
    
    @Resource
    private cn.iocoder.yudao.module.system.service.examcontrolline.ExamControlLineService examControlLineService;
    
    @Resource
    private cn.iocoder.yudao.module.system.dal.mysql.topscorerecord.TopScoreRecordMapper topScoreRecordMapper;
    
    @Resource
    private cn.iocoder.yudao.module.system.service.gugu.ProvinceScoreService provinceScoreService;

    @Resource
    private cn.iocoder.yudao.module.system.service.goal.StudentMajorGroupGoalService studentMajorGroupGoalService;

    @Override
    public StudentDashboardRespVO getStudentDashboard(@Valid StudentDashboardReqVO reqVO) {
        log.info("获取学生看板数据，学生ID: {}, 考试ID: {}", reqVO.getStudentId(), reqVO.getExamId());
        
        // 获取学生基本信息
        StudentDashboardRespVO.StudentBasicInfo studentInfo = getStudentBasicInfo(reqVO.getStudentId());
        if (studentInfo == null) {
            throw ServiceExceptionUtil.exception(USER_NOT_EXISTS);
        }

        // 确定目标考试ID：如果传入了examId则使用它，否则获取最新考试
        Long targetExamId = reqVO.getExamId();
        StudentDashboardRespVO.LatestExamInfo targetExam = null;
        
        if (targetExamId != null) {
            // 获取指定考试的信息
            targetExam = getSpecificExamInfo(reqVO.getStudentId(), targetExamId);
            if (targetExam == null) {
                throw ServiceExceptionUtil.exception(EXAM_SCORE_NOT_EXISTS);
            }
        } else {
            // 获取最新考试信息
            targetExam = getLatestExamInfo(reqVO.getStudentId());
            if (targetExam == null) {
                throw ServiceExceptionUtil.exception(EXAM_SCORE_NOT_EXISTS);
            }
            targetExamId = targetExam.getExamId();
        }

        StudentDashboardRespVO respVO = new StudentDashboardRespVO();
        respVO.setStudentInfo(studentInfo);
        respVO.setLatestExam(targetExam);

        // 获取排名信息
        if (Boolean.TRUE.equals(reqVO.getIncludeClassRank()) || Boolean.TRUE.equals(reqVO.getIncludeGradeRank())) {
            respVO.setRanking(getRankingInfo(reqVO.getStudentId(), targetExamId));
        }

        // 获取各科排名
        if (Boolean.TRUE.equals(reqVO.getIncludeSubjectRank())) {
            respVO.setSubjectRanking(getSubjectRankingInfo(reqVO.getStudentId(), targetExamId));
        }

        // 获取成绩趋势
        if (Boolean.TRUE.equals(reqVO.getIncludeTrend())) {
            respVO.setScoreTrend(getScoreTrendInfo(reqVO.getStudentId(), reqVO.getTrendLimit()));
        }

        // 获取分数分布
        if (Boolean.TRUE.equals(reqVO.getIncludeDistribution())) {
            respVO.setScoreDistribution(getScoreDistributionInfo(reqVO.getStudentId(), targetExamId));
        }

        // 获取考试对比数据
        if (CollUtil.isNotEmpty(reqVO.getExamIds())) {
            respVO.setExamComparisons(getExamComparisonInfo(reqVO.getStudentId(), reqVO.getExamIds()));
        }

        // 获取等效位次和等效分信息
        if (Boolean.TRUE.equals(reqVO.getIncludeEquivalentScoreRank())) {
            // 根据考试ID获取特控线ID
            Long controlLineId = getControlLineIdByExamId(targetExamId);
            if (controlLineId != null) {
                respVO.setEquivalentScoreRank(getStudentEquivalentScoreRank(reqVO.getStudentId(), targetExamId, controlLineId));
            } else {
                // 当没有特控线时，尝试使用省控线进行等效位次计算
                log.info("未找到考试ID为{}的特控线配置，尝试使用省控线进行等效位次计算", targetExamId);
                respVO.setEquivalentScoreRank(getStudentEquivalentScoreRankWithProvinceControlLine(reqVO.getStudentId(), targetExamId));
            }
        }
        
        // 获取目标分析
        if (Boolean.TRUE.equals(reqVO.getIncludeGoalAnalysis())) {
            respVO.setGoalAnalysis(getGoalAnalysis(reqVO.getStudentId(), respVO.getEquivalentScoreRank()));
        }
        
        // 获取最高分记录信息
        respVO.setTopScoreRecords(getTopScoreRecords(reqVO.getStudentId(), targetExamId));
        
        // 获取学生参与的所有考试列表
        respVO.setStudentExams(getStudentExamList(reqVO.getStudentId()));

        return respVO;
    }

    @Override
    public StudentRankingRespVO getStudentRanking(@Valid StudentRankingReqVO reqVO) {
        log.info("获取学生排名信息，学生ID: {}, 考试ID: {}", reqVO.getStudentId(), reqVO.getExamId());
        
        // 获取学生成绩
        ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(reqVO.getExamId(), reqVO.getStudentId());
        if (examScore == null) {
            throw ServiceExceptionUtil.exception(EXAM_SCORE_NOT_EXISTS);
        }

        StudentRankingRespVO respVO = new StudentRankingRespVO();
        
        // 设置学生基本信息
        StudentRankingRespVO.StudentBasicInfo studentInfo = new StudentRankingRespVO.StudentBasicInfo();
        studentInfo.setStudentId(reqVO.getStudentId());
        studentInfo.setStudentName(examScore.getStudentName());
        studentInfo.setStudentNo(examScore.getStudentNo());
        studentInfo.setTotalScore(examScore.getTotalScore());
        respVO.setStudentInfo(studentInfo);

        // 获取班级排名信息
        if ("ALL".equals(reqVO.getRankType()) || "CLASS".equals(reqVO.getRankType())) {
            respVO.setClassRanking(getClassRankingInfo(reqVO.getExamId(), reqVO.getStudentId()));
        }

        // 获取年级排名信息
        if ("ALL".equals(reqVO.getRankType()) || "GRADE".equals(reqVO.getRankType())) {
            respVO.setGradeRanking(getGradeRankingInfo(reqVO.getExamId(), reqVO.getStudentId()));
        }

        // 获取各科排名信息
        if ("ALL".equals(reqVO.getRankType()) || "SUBJECT".equals(reqVO.getRankType())) {
            respVO.setSubjectRankings(getSubjectRankingList(reqVO.getExamId(), reqVO.getStudentId(), reqVO.getSubjectName()));
        }

        return respVO;
    }

    @Override
    public StudentExamComparisonRespVO getStudentExamComparison(@Valid StudentExamComparisonReqVO reqVO) {
        log.info("获取学生考试对比数据，学生ID: {}, 考试IDs: {}", reqVO.getStudentId(), reqVO.getExamIds());
        
        StudentExamComparisonRespVO respVO = new StudentExamComparisonRespVO();
        
        // 获取学生基本信息
        StudentExamComparisonRespVO.StudentBasicInfo studentInfo = getStudentBasicInfoForComparison(reqVO.getStudentId());
        respVO.setStudentInfo(studentInfo);

        // 获取考试对比数据
        List<StudentExamComparisonRespVO.ExamComparisonData> examComparisons = 
            getExamComparisonData(reqVO.getStudentId(), reqVO.getExamIds());
        respVO.setExamComparisons(examComparisons);

        // 趋势分析
        if (Boolean.TRUE.equals(reqVO.getIncludeTrendAnalysis())) {
            respVO.setTotalScoreTrend(calculateTotalScoreTrend(examComparisons));
            respVO.setSubjectTrends(calculateSubjectTrends(examComparisons));
        }

        // 排名变化分析
        if (Boolean.TRUE.equals(reqVO.getIncludeRankingChange())) {
            respVO.setRankingTrend(calculateRankingTrend(examComparisons));
        }

        // 进步分析
        respVO.setProgressAnalysis(calculateProgressAnalysis(examComparisons));

        return respVO;
    }

    @Override
    public Integer getStudentClassRank(Long studentId, Long examId) {
        return examScoreMapper.selectClassRankByExamIdAndStudentId(examId, studentId);
    }

    @Override
    public Integer getStudentGradeRank(Long studentId, Long examId) {
        return examScoreMapper.selectGradeRankByExamIdAndStudentId(examId, studentId);
    }

    @Override
    public Integer getStudentSubjectClassRank(Long studentId, Long examId, String subjectName) {
        return examScoreMapper.selectSubjectClassRankByExamIdAndStudentId(examId, studentId, subjectName);
    }

    @Override
    public Integer getStudentSubjectGradeRank(Long studentId, Long examId, String subjectName) {
        return examScoreMapper.selectSubjectGradeRankByExamIdAndStudentId(examId, studentId, subjectName);
    }

    // ==================== 私有方法 ====================

    /**
     * 根据考试ID获取特控线ID
     * 如果有多个特控线，返回第一个
     */
    private Long getControlLineIdByExamId(Long examId) {
        try {
            List<cn.iocoder.yudao.module.system.dal.dataobject.examcontrolline.ExamControlLineDO> controlLines = 
                    examControlLineService.getExamControlLineListByExamId(examId);
            if (CollUtil.isNotEmpty(controlLines)) {
                return controlLines.get(0).getId(); // 返回第一个特控线ID
            }
        } catch (Exception e) {
            log.error("获取考试ID为{}的特控线配置失败", examId, e);
        }
        return null;
    }

    /**
     * 获取学生基本信息
     */
    private StudentDashboardRespVO.StudentBasicInfo getStudentBasicInfo(Long studentId) {
        // 获取学生班级信息
        List<ExamClassStudentDO> classStudents = examClassStudentMapper.selectListByStudentId(studentId);
        if (CollUtil.isEmpty(classStudents)) {
            return null;
        }

        ExamClassStudentDO classStudent = classStudents.get(0); // 取第一个班级
        ExamClassDO examClass = examClassMapper.selectById(classStudent.getClassId());
        if (examClass == null) {
            return null;
        }

        StudentDashboardRespVO.StudentBasicInfo studentInfo = new StudentDashboardRespVO.StudentBasicInfo();
        studentInfo.setStudentId(studentId);
        studentInfo.setStudentName(classStudent.getStudentName());
        studentInfo.setStudentNo(classStudent.getStudentNo());
        studentInfo.setClassId(examClass.getId());
        studentInfo.setClassName(examClass.getClassName());
        studentInfo.setGrade(examClass.getGrade());

        return studentInfo;
    }

    /**
     * 获取指定考试信息
     */
    private StudentDashboardRespVO.LatestExamInfo getSpecificExamInfo(Long studentId, Long examId) {
        // 获取学生指定考试的成绩
        ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(examId, studentId);
        if (examScore == null) {
            return null;
        }

        ExamTestDO examTest = examTestMapper.selectById(examId);
        if (examTest == null) {
            return null;
        }

        StudentDashboardRespVO.LatestExamInfo examInfo = new StudentDashboardRespVO.LatestExamInfo();
        examInfo.setExamId(examTest.getId());
        examInfo.setExamName(examTest.getExamName());
        examInfo.setExamType(examTest.getExamType());
        examInfo.setExamDate(examTest.getExamDate());
        examInfo.setTotalScore(examScore.getTotalScore());
        examInfo.setFullScore(examTest.getTotalScore());

        // 设置各科成绩
        Map<String, BigDecimal> subjectScores = new HashMap<>();
        if (examScore.getChineseScore() != null) subjectScores.put("语文", examScore.getChineseScore());
        if (examScore.getMathScore() != null) subjectScores.put("数学", examScore.getMathScore());
        if (examScore.getEnglishScore() != null) subjectScores.put("英语", examScore.getEnglishScore());
        if (examScore.getPhysicsScore() != null) subjectScores.put("物理", examScore.getPhysicsScore());
        if (examScore.getChemistryScore() != null) subjectScores.put("化学", examScore.getChemistryScore());
        if (examScore.getBiologyScore() != null) subjectScores.put("生物", examScore.getBiologyScore());
        if (examScore.getPoliticsScore() != null) subjectScores.put("政治", examScore.getPoliticsScore());
        if (examScore.getHistoryScore() != null) subjectScores.put("历史", examScore.getHistoryScore());
        if (examScore.getGeographyScore() != null) subjectScores.put("地理", examScore.getGeographyScore());
        examInfo.setSubjectScores(subjectScores);
        
        // 设置新增字段
        examInfo.setSubjectCombination(examScore.getSubjectCombination());
        examInfo.setFirstSubject(examScore.getFirstSubject());
        examInfo.setSecondSubject(examScore.getSecondSubject());
        examInfo.setProvince(examScore.getProvince());
        examInfo.setTotalScoreAssigned(examScore.getTotalScoreAssigned());
        examInfo.setTotalUnionRank(examScore.getTotalUnionRank());
        examInfo.setCombinationRank(examScore.getCombinationRank());
        examInfo.setSchoolRank(examScore.getSchoolRank());
        
        // 设置各科赋分成绩（如果有的话）
        Map<String, BigDecimal> subjectAssignedScores = new HashMap<>();
        // 从SubjectScoreDetail表中获取赋分成绩
        List<SubjectScoreDetailDO> subjectDetails = subjectScoreDetailMapper.selectByExamIdAndStudentId(examId, studentId);
        if (CollUtil.isNotEmpty(subjectDetails)) {
            for (SubjectScoreDetailDO detail : subjectDetails) {
                if (detail.getAssignedScore() != null) {
                    subjectAssignedScores.put(detail.getSubjectName(), detail.getAssignedScore());
                }
            }
        }
        examInfo.setSubjectAssignedScores(subjectAssignedScores);

        return examInfo;
    }

    /**
     * 获取最新考试信息
     */
    private StudentDashboardRespVO.LatestExamInfo getLatestExamInfo(Long studentId) {
        List<ExamScoreDO> scores = examScoreMapper.selectListByStudentId(studentId);
        if (CollUtil.isEmpty(scores)) {
            return null;
        }

        ExamScoreDO latestScore = scores.get(0); // 已按创建时间倒序排列
        ExamTestDO examTest = examTestMapper.selectById(latestScore.getExamId());
        if (examTest == null) {
            return null;
        }

        StudentDashboardRespVO.LatestExamInfo latestExam = new StudentDashboardRespVO.LatestExamInfo();
        latestExam.setExamId(examTest.getId());
        latestExam.setExamName(examTest.getExamName());
        latestExam.setExamType(examTest.getExamType());
        latestExam.setExamDate(examTest.getExamDate());
        latestExam.setTotalScore(latestScore.getTotalScore());
        latestExam.setFullScore(examTest.getTotalScore());

        // 设置各科成绩
        Map<String, BigDecimal> subjectScores = new HashMap<>();
        if (latestScore.getChineseScore() != null) subjectScores.put("语文", latestScore.getChineseScore());
        if (latestScore.getMathScore() != null) subjectScores.put("数学", latestScore.getMathScore());
        if (latestScore.getEnglishScore() != null) subjectScores.put("英语", latestScore.getEnglishScore());
        if (latestScore.getPhysicsScore() != null) subjectScores.put("物理", latestScore.getPhysicsScore());
        if (latestScore.getChemistryScore() != null) subjectScores.put("化学", latestScore.getChemistryScore());
        if (latestScore.getBiologyScore() != null) subjectScores.put("生物", latestScore.getBiologyScore());
        if (latestScore.getPoliticsScore() != null) subjectScores.put("政治", latestScore.getPoliticsScore());
        if (latestScore.getHistoryScore() != null) subjectScores.put("历史", latestScore.getHistoryScore());
        if (latestScore.getGeographyScore() != null) subjectScores.put("地理", latestScore.getGeographyScore());
        latestExam.setSubjectScores(subjectScores);
        
        // 设置新增字段
        latestExam.setSubjectCombination(latestScore.getSubjectCombination());
        latestExam.setFirstSubject(latestScore.getFirstSubject());
        latestExam.setSecondSubject(latestScore.getSecondSubject());
        latestExam.setProvince(latestScore.getProvince());
        latestExam.setTotalScoreAssigned(latestScore.getTotalScoreAssigned());
        latestExam.setTotalUnionRank(latestScore.getTotalUnionRank());
        latestExam.setCombinationRank(latestScore.getCombinationRank());
        latestExam.setSchoolRank(latestScore.getSchoolRank());
        
        // 设置各科赋分成绩（如果有的话）
        Map<String, BigDecimal> subjectAssignedScores = new HashMap<>();
        // 从SubjectScoreDetail表中获取赋分成绩
        List<SubjectScoreDetailDO> subjectDetails = subjectScoreDetailMapper.selectByExamIdAndStudentId(examTest.getId(), studentId);
        if (CollUtil.isNotEmpty(subjectDetails)) {
            for (SubjectScoreDetailDO detail : subjectDetails) {
                if (detail.getAssignedScore() != null) {
                    subjectAssignedScores.put(detail.getSubjectName(), detail.getAssignedScore());
                }
            }
        }
        latestExam.setSubjectAssignedScores(subjectAssignedScores);

        return latestExam;
    }

    /**
     * 获取排名信息
     * 优化：直接从ExamScoreDO中获取已有的排名数据，避免复杂查询
     */
    private StudentDashboardRespVO.RankingInfo getRankingInfo(Long studentId, Long examId) {
        ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(examId, studentId);
        if (examScore == null) {
            return null;
        }

        StudentDashboardRespVO.RankingInfo ranking = new StudentDashboardRespVO.RankingInfo();
        
        // 直接使用ExamScoreDO中已有的排名数据
        ranking.setClassRank(examScore.getClassRank());
        ranking.setGradeRank(examScore.getGradeRank());
        ranking.setSchoolRank(examScore.getSchoolRank());
        ranking.setUnionRank(examScore.getTotalUnionRank());
        ranking.setCombinationRank(examScore.getCombinationRank());
        ranking.setSubjectCombination(examScore.getSubjectCombination());

        // 获取班级和年级总人数
        // 优化：直接从成绩表统计，避免依赖考试表关联
        Integer classTotalCount = null;
        Integer gradeTotalCount = null;
        
        if (examScore.getClassId() != null) {
            // 直接统计同班级同考试的学生数量
            classTotalCount = Math.toIntExact(examScoreMapper.selectCount(new LambdaQueryWrapperX<ExamScoreDO>()
                    .eq(ExamScoreDO::getExamId, examId)
                    .eq(ExamScoreDO::getClassId, examScore.getClassId())));
        }
        
        // 如果没有年级排名，尝试使用校内排名作为替代
        if (examScore.getGradeRank() == null && examScore.getSchoolRank() != null) {
            ranking.setGradeRank(examScore.getSchoolRank());
            // 统计同考试的总学生数作为年级总数
            gradeTotalCount = Math.toIntExact(examScoreMapper.selectCount(new LambdaQueryWrapperX<ExamScoreDO>()
                    .eq(ExamScoreDO::getExamId, examId)));
        } else {
            // 尝试原有方法获取年级总人数
            gradeTotalCount = examScoreMapper.selectGradeTotalCountByExamId(examId);
        }
        
        ranking.setClassTotalCount(classTotalCount);
        ranking.setGradeTotalCount(gradeTotalCount);

        // 计算百分位
        if (examScore.getClassRank() != null && classTotalCount != null && classTotalCount > 0 && examScore.getClassRank() > 0) {
            double classPercentileValue = 100.0 * (classTotalCount - examScore.getClassRank() + 1) / classTotalCount;
            if (!Double.isNaN(classPercentileValue) && !Double.isInfinite(classPercentileValue)) {
                BigDecimal classPercentile = BigDecimal.valueOf(classPercentileValue)
                        .setScale(1, RoundingMode.HALF_UP);
                ranking.setClassPercentile(classPercentile);
            }
        }

        if (examScore.getGradeRank() != null && gradeTotalCount != null && gradeTotalCount > 0 && examScore.getGradeRank() > 0) {
            double gradePercentileValue = 100.0 * (gradeTotalCount - examScore.getGradeRank() + 1) / gradeTotalCount;
            if (!Double.isNaN(gradePercentileValue) && !Double.isInfinite(gradePercentileValue)) {
                BigDecimal gradePercentile = BigDecimal.valueOf(gradePercentileValue)
                        .setScale(1, RoundingMode.HALF_UP);
                ranking.setGradePercentile(gradePercentile);
            }
        }

        return ranking;
    }

    /**
     * 获取各科排名信息
     */
    private Map<String, StudentDashboardRespVO.SubjectRankInfo> getSubjectRankingInfo(Long studentId, Long examId) {
        ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(examId, studentId);
        if (examScore == null) {
            return new LinkedHashMap<>();
        }

        // 使用 LinkedHashMap 保持插入顺序
        Map<String, StudentDashboardRespVO.SubjectRankInfo> subjectRanking = new LinkedHashMap<>();

        // 获取班级和年级统计信息
        Map<String, Object> classStats = examScoreMapper.selectClassStatistics(examId);
        Map<String, Object> gradeStats = examScoreMapper.selectGradeStatistics(examId);

        // 处理各科成绩
        addSubjectRankInfo(subjectRanking, "语文", examScore.getChineseScore(), BigDecimal.valueOf(150),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "数学", examScore.getMathScore(), BigDecimal.valueOf(150),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "英语", examScore.getEnglishScore(), BigDecimal.valueOf(150),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "物理", examScore.getPhysicsScore(), BigDecimal.valueOf(100),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "化学", examScore.getChemistryScore(), BigDecimal.valueOf(100),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "生物", examScore.getBiologyScore(), BigDecimal.valueOf(100),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "政治", examScore.getPoliticsScore(), BigDecimal.valueOf(100),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "历史", examScore.getHistoryScore(), BigDecimal.valueOf(100),
                          studentId, examId, classStats, gradeStats);
        addSubjectRankInfo(subjectRanking, "地理", examScore.getGeographyScore(), BigDecimal.valueOf(100),
                          studentId, examId, classStats, gradeStats);
        
        // 处理小语种成绩
        addMinorityLanguageRankInfo(subjectRanking, "日语", 
                examScore.getJapaneseOriginalScore(), examScore.getJapaneseAssignedScore(),
                examScore.getJapaneseGradeLevel(), examScore.getJapaneseClassRank(), 
                examScore.getJapaneseSchoolRank(), examScore.getJapaneseUnionRank(),
                BigDecimal.valueOf(150), studentId, examId, classStats, gradeStats);
        addMinorityLanguageRankInfo(subjectRanking, "俄语", 
                examScore.getRussianOriginalScore(), examScore.getRussianAssignedScore(),
                examScore.getRussianGradeLevel(), examScore.getRussianClassRank(), 
                examScore.getRussianSchoolRank(), examScore.getRussianUnionRank(),
                BigDecimal.valueOf(150), studentId, examId, classStats, gradeStats);
        addMinorityLanguageRankInfo(subjectRanking, "西班牙语", 
                examScore.getSpanishOriginalScore(), examScore.getSpanishAssignedScore(),
                examScore.getSpanishGradeLevel(), examScore.getSpanishClassRank(), 
                examScore.getSpanishSchoolRank(), examScore.getSpanishUnionRank(),
                BigDecimal.valueOf(150), studentId, examId, classStats, gradeStats);

        return subjectRanking;
    }

    /**
     * 添加科目排名信息
     * 优化：直接从科目成绩详情表中获取已有的排名和分数数据，避免复杂查询
     */
    private void addSubjectRankInfo(Map<String, StudentDashboardRespVO.SubjectRankInfo> subjectRanking,
                                   String subjectName, BigDecimal score, BigDecimal fullScore,
                                   Long studentId, Long examId,
                                   Map<String, Object> classStats, Map<String, Object> gradeStats) {
        if (score == null) {
            return;
        }

        StudentDashboardRespVO.SubjectRankInfo rankInfo = new StudentDashboardRespVO.SubjectRankInfo();
        rankInfo.setSubjectName(subjectName);
        
        // 优先从科目成绩详情表获取数据
        SubjectScoreDetailDO subjectDetail = subjectScoreDetailMapper.selectByExamIdAndStudentIdAndSubject(examId, studentId, subjectName);
        
        if (subjectDetail != null) {
            // 设置原始分和赋分
            rankInfo.setOriginalScore(subjectDetail.getOriginalScore());
            rankInfo.setAssignedScore(subjectDetail.getAssignedScore());
            
            // 使用科目详情表中的分数（优先使用赋分，如果没有则使用原始分）
            BigDecimal finalScore = subjectDetail.getAssignedScore() != null ? 
                subjectDetail.getAssignedScore() : subjectDetail.getOriginalScore();
            rankInfo.setScore(finalScore != null ? finalScore : score);
            
            // 设置等级信息
            rankInfo.setGradeLevel(subjectDetail.getGradeLevel());
            
            // 直接使用科目详情表中的排名数据
            rankInfo.setClassRank(subjectDetail.getClassRank());
            rankInfo.setSchoolRank(subjectDetail.getSchoolRank());
            rankInfo.setUnionRank(subjectDetail.getUnionRank());
            // 使用校内排名作为年级排名（如果有联考排名可以考虑使用unionRank）
            rankInfo.setGradeRank(subjectDetail.getSchoolRank());
            
            // 设置是否为选考科目
            rankInfo.setIsElectiveSubject(subjectDetail.getIsElectiveSubject() != null && subjectDetail.getIsElectiveSubject() == 1);
        } else {
            // 如果科目详情表中没有数据，则使用传入的分数
            rankInfo.setScore(score);
            rankInfo.setIsElectiveSubject(false);
            log.warn("科目成绩详情表中未找到数据，examId: {}, studentId: {}, subjectName: {}", examId, studentId, subjectName);
        }
        
        rankInfo.setFullScore(fullScore);

        // 设置平均分（这里简化处理，实际应该按科目计算）
        if (classStats.get("avgScore") != null) {
            rankInfo.setClassAvgScore((BigDecimal) classStats.get("avgScore"));
        }
        if (gradeStats.get("avgScore") != null) {
            rankInfo.setGradeAvgScore((BigDecimal) gradeStats.get("avgScore"));
        }

        // 计算超过百分比（仅在有排名数据时计算）
        Integer classRank = rankInfo.getClassRank();
        Integer gradeRank = rankInfo.getGradeRank();
        
        if (classRank != null && classRank > 0) {
            Integer classTotalCount = examScoreMapper.selectClassTotalCountByExamId(examId);
            if (classTotalCount != null && classTotalCount > 0) {
                double classBeatPercentageValue = 100.0 * (classTotalCount - classRank) / classTotalCount;
                if (!Double.isNaN(classBeatPercentageValue) && !Double.isInfinite(classBeatPercentageValue)) {
                    BigDecimal classBeatPercentage = BigDecimal.valueOf(classBeatPercentageValue)
                            .setScale(1, RoundingMode.HALF_UP);
                    rankInfo.setClassBeatPercentage(classBeatPercentage);
                }
            }
        }

        if (gradeRank != null && gradeRank > 0) {
            Integer gradeTotalCount = examScoreMapper.selectGradeTotalCountByExamId(examId);
            if (gradeTotalCount != null && gradeTotalCount > 0) {
                double gradeBeatPercentageValue = 100.0 * (gradeTotalCount - gradeRank) / gradeTotalCount;
                if (!Double.isNaN(gradeBeatPercentageValue) && !Double.isInfinite(gradeBeatPercentageValue)) {
                    BigDecimal gradeBeatPercentage = BigDecimal.valueOf(gradeBeatPercentageValue)
                            .setScale(1, RoundingMode.HALF_UP);
                    rankInfo.setGradeBeatPercentage(gradeBeatPercentage);
                }
            }
        }

        subjectRanking.put(subjectName, rankInfo);
    }

    /**
     * 添加小语种科目排名信息
     * 小语种成绩直接从 ExamScoreDO 中获取原始分、赋分和排名信息
     */
    private void addMinorityLanguageRankInfo(Map<String, StudentDashboardRespVO.SubjectRankInfo> subjectRanking,
                                            String subjectName, BigDecimal originalScore, BigDecimal assignedScore,
                                            String gradeLevel, Integer classRank, Integer schoolRank, Integer unionRank,
                                            BigDecimal fullScore, Long studentId, Long examId,
                                            Map<String, Object> classStats, Map<String, Object> gradeStats) {
        // 如果原始分和赋分都为空，说明该学生没有选择该小语种科目
        if (originalScore == null && assignedScore == null) {
            return;
        }

        StudentDashboardRespVO.SubjectRankInfo rankInfo = new StudentDashboardRespVO.SubjectRankInfo();
        rankInfo.setSubjectName(subjectName);
        
        // 设置原始分和赋分
        rankInfo.setOriginalScore(originalScore);
        rankInfo.setAssignedScore(assignedScore);
        
        // 使用赋分作为显示分数（如果有赋分），否则使用原始分
        BigDecimal displayScore = assignedScore != null ? assignedScore : originalScore;
        rankInfo.setScore(displayScore);
        
        // 设置等级信息
        rankInfo.setGradeLevel(gradeLevel);
        
        // 设置满分
        rankInfo.setFullScore(fullScore);
        
        // 直接使用 ExamScoreDO 中的排名数据
        rankInfo.setClassRank(classRank);
        rankInfo.setSchoolRank(schoolRank);
        rankInfo.setUnionRank(unionRank);
        // 使用校内排名作为年级排名
        rankInfo.setGradeRank(schoolRank);
        
        // 小语种通常是选考科目
        rankInfo.setIsElectiveSubject(true);
        
        // 设置平均分（这里简化处理，实际应该按科目计算）
        if (classStats.get("avgScore") != null) {
            rankInfo.setClassAvgScore((BigDecimal) classStats.get("avgScore"));
        }
        if (gradeStats.get("avgScore") != null) {
            rankInfo.setGradeAvgScore((BigDecimal) gradeStats.get("avgScore"));
        }

        // 计算超过百分比（仅在有排名数据时计算）
        if (classRank != null && classRank > 0) {
            Integer classTotalCount = examScoreMapper.selectClassTotalCountByExamId(examId);
            if (classTotalCount != null && classTotalCount > 0) {
                double classBeatPercentageValue = 100.0 * (classTotalCount - classRank) / classTotalCount;
                if (!Double.isNaN(classBeatPercentageValue) && !Double.isInfinite(classBeatPercentageValue)) {
                    BigDecimal classBeatPercentage = BigDecimal.valueOf(classBeatPercentageValue)
                            .setScale(1, RoundingMode.HALF_UP);
                    rankInfo.setClassBeatPercentage(classBeatPercentage);
                }
            }
        }

        if (schoolRank != null && schoolRank > 0) {
            Integer gradeTotalCount = examScoreMapper.selectGradeTotalCountByExamId(examId);
            if (gradeTotalCount != null && gradeTotalCount > 0) {
                double gradeBeatPercentageValue = 100.0 * (gradeTotalCount - schoolRank) / gradeTotalCount;
                if (!Double.isNaN(gradeBeatPercentageValue) && !Double.isInfinite(gradeBeatPercentageValue)) {
                    BigDecimal gradeBeatPercentage = BigDecimal.valueOf(gradeBeatPercentageValue)
                            .setScale(1, RoundingMode.HALF_UP);
                    rankInfo.setGradeBeatPercentage(gradeBeatPercentage);
                }
            }
        }

        subjectRanking.put(subjectName, rankInfo);
        log.debug("添加小语种科目排名信息: {}, 原始分: {}, 赋分: {}, 等级: {}, 班级排名: {}, 校内排名: {}", 
                subjectName, originalScore, assignedScore, gradeLevel, classRank, schoolRank);
    }

    /**
     * 获取成绩趋势信息
     */
    private StudentDashboardRespVO.ScoreTrendInfo getScoreTrendInfo(Long studentId, Integer trendLimit) {
        if (trendLimit == null || trendLimit <= 0) {
            trendLimit = 5;
        }

        List<Map<String, Object>> historyData = examScoreMapper.selectStudentScoreHistory(studentId, trendLimit);
        if (CollUtil.isEmpty(historyData)) {
            return null;
        }

        StudentDashboardRespVO.ScoreTrendInfo trendInfo = new StudentDashboardRespVO.ScoreTrendInfo();

        // 构建趋势数据点
        List<StudentDashboardRespVO.TrendDataPoint> trendData = new ArrayList<>();
        for (Map<String, Object> data : historyData) {
            StudentDashboardRespVO.TrendDataPoint point = new StudentDashboardRespVO.TrendDataPoint();
            point.setExamId(((Number) data.get("exam_id")).longValue());
            point.setExamName((String) data.get("exam_name"));
            point.setExamDate((LocalDateTime) data.get("exam_date"));
            point.setTotalScore((BigDecimal) data.get("total_score"));
            point.setClassRank((Integer) data.get("class_rank"));
            point.setGradeRank((Integer) data.get("grade_rank"));

            // 设置各科成绩
            Map<String, BigDecimal> subjectScores = new HashMap<>();
            if (data.get("chinese_score") != null) subjectScores.put("语文", (BigDecimal) data.get("chinese_score"));
            if (data.get("math_score") != null) subjectScores.put("数学", (BigDecimal) data.get("math_score"));
            if (data.get("english_score") != null) subjectScores.put("英语", (BigDecimal) data.get("english_score"));
            if (data.get("physics_score") != null) subjectScores.put("物理", (BigDecimal) data.get("physics_score"));
            if (data.get("chemistry_score") != null) subjectScores.put("化学", (BigDecimal) data.get("chemistry_score"));
            if (data.get("biology_score") != null) subjectScores.put("生物", (BigDecimal) data.get("biology_score"));
            if (data.get("politics_score") != null) subjectScores.put("政治", (BigDecimal) data.get("politics_score"));
            if (data.get("history_score") != null) subjectScores.put("历史", (BigDecimal) data.get("history_score"));
            if (data.get("geography_score") != null) subjectScores.put("地理", (BigDecimal) data.get("geography_score"));
            point.setSubjectScores(subjectScores);
            
            // 设置新增字段
            if (data.get("total_score_assigned") != null) {
                point.setTotalScoreAssigned((BigDecimal) data.get("total_score_assigned"));
            }
            if (data.get("total_union_rank") != null) {
                point.setTotalUnionRank((Integer) data.get("total_union_rank"));
            }
            if (data.get("combination_rank") != null) {
                point.setCombinationRank((Integer) data.get("combination_rank"));
            }
            if (data.get("school_rank") != null) {
                point.setSchoolRank((Integer) data.get("school_rank"));
            }

            trendData.add(point);
        }

        trendInfo.setTrendData(trendData);

        // 计算总分趋势
        List<BigDecimal> totalScores = trendData.stream()
                .map(StudentDashboardRespVO.TrendDataPoint::getTotalScore)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        trendInfo.setTotalScoreTrend(calculateTrendAnalysis(totalScores));

        // 计算各科趋势
        Map<String, StudentDashboardRespVO.TrendAnalysis> subjectTrends = new HashMap<>();
        Set<String> allSubjects = trendData.stream()
                .flatMap(point -> point.getSubjectScores().keySet().stream())
                .collect(Collectors.toSet());

        for (String subject : allSubjects) {
            List<BigDecimal> subjectScores = trendData.stream()
                    .map(point -> point.getSubjectScores().get(subject))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            if (!subjectScores.isEmpty()) {
                subjectTrends.put(subject, calculateTrendAnalysis(subjectScores));
            }
        }
        trendInfo.setSubjectTrends(subjectTrends);

        return trendInfo;
    }

    /**
     * 计算趋势分析
     */
    private StudentDashboardRespVO.TrendAnalysis calculateTrendAnalysis(List<BigDecimal> scores) {
        if (CollUtil.isEmpty(scores)) {
            return null;
        }

        StudentDashboardRespVO.TrendAnalysis analysis = new StudentDashboardRespVO.TrendAnalysis();

        // 基本统计
        BigDecimal max = scores.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal min = scores.stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        BigDecimal avg = scores.stream()
                .reduce(BigDecimal.ZERO, BigDecimal::add)
                .divide(BigDecimal.valueOf(scores.size()), 2, RoundingMode.HALF_UP);

        analysis.setMaxValue(max);
        analysis.setMinValue(min);
        analysis.setAverageValue(avg);
        analysis.setChangeRange(max.subtract(min));

        // 趋势方向判断
        if (scores.size() >= 2) {
            BigDecimal first = scores.get(scores.size() - 1); // 最早的成绩
            BigDecimal last = scores.get(0); // 最新的成绩
            BigDecimal change = last.subtract(first);

            analysis.setChangeAmount(change);
            if (first.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal changePercentage = change.divide(first, 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                analysis.setChangePercentage(changePercentage);
            }

            // 判断趋势方向
            if (change.compareTo(BigDecimal.valueOf(10)) > 0) {
                analysis.setTrendDirection("UP");
            } else if (change.compareTo(BigDecimal.valueOf(-10)) < 0) {
                analysis.setTrendDirection("DOWN");
            } else {
                analysis.setTrendDirection("STABLE");
            }
        }

        // 计算连续上升/下降次数
        int consecutiveUp = 0;
        int consecutiveDown = 0;
        int currentUp = 0;
        int currentDown = 0;

        for (int i = 1; i < scores.size(); i++) {
            BigDecimal current = scores.get(i - 1);
            BigDecimal previous = scores.get(i);

            if (current.compareTo(previous) > 0) {
                currentUp++;
                currentDown = 0;
            } else if (current.compareTo(previous) < 0) {
                currentDown++;
                currentUp = 0;
            } else {
                currentUp = 0;
                currentDown = 0;
            }

            consecutiveUp = Math.max(consecutiveUp, currentUp);
            consecutiveDown = Math.max(consecutiveDown, currentDown);
        }

        analysis.setConsecutiveUpCount(consecutiveUp);
        analysis.setConsecutiveDownCount(consecutiveDown);

        // 计算波动系数（标准差/平均值）
        if (avg.compareTo(BigDecimal.ZERO) > 0 && scores.size() > 1) {
            double variance = scores.stream()
                    .mapToDouble(score -> Math.pow(score.subtract(avg).doubleValue(), 2))
                    .average()
                    .orElse(0.0);
            double stdDev = Math.sqrt(variance);
            BigDecimal volatilityCoefficient = BigDecimal.valueOf(stdDev)
                    .divide(avg, 4, RoundingMode.HALF_UP);
            analysis.setVolatilityCoefficient(volatilityCoefficient);
        }

        return analysis;
    }

    /**
     * 获取分数分布信息
     */
    private StudentDashboardRespVO.ScoreDistributionInfo getScoreDistributionInfo(Long studentId, Long examId) {
        ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(examId, studentId);
        if (examScore == null) {
            return null;
        }

        StudentDashboardRespVO.ScoreDistributionInfo distributionInfo = new StudentDashboardRespVO.ScoreDistributionInfo();

        // 获取学生位置信息
        StudentDashboardRespVO.StudentPositionInfo positionInfo = new StudentDashboardRespVO.StudentPositionInfo();
        positionInfo.setStudentScore(examScore.getTotalScore());

        // 获取年级统计信息
        Map<String, Object> gradeStats = examScoreMapper.selectGradeStatistics(examId);
        Integer gradeTotalCount = examScoreMapper.selectGradeTotalCountByExamId(examId);

        if (examScore.getGradeRank() != null && gradeTotalCount != null && gradeTotalCount > 0 && examScore.getGradeRank() > 0) {
            positionInfo.setStudentsBelow(gradeTotalCount - examScore.getGradeRank());
            positionInfo.setStudentsAbove(examScore.getGradeRank() - 1);
            positionInfo.setStudentsEqual(1); // 简化处理

            double percentileValue = 100.0 * (gradeTotalCount - examScore.getGradeRank() + 1) / gradeTotalCount;
            if (!Double.isNaN(percentileValue) && !Double.isInfinite(percentileValue)) {
                BigDecimal percentileRank = BigDecimal.valueOf(percentileValue)
                        .setScale(1, RoundingMode.HALF_UP);
                positionInfo.setPercentileRank(percentileRank);
            }
        }
        distributionInfo.setStudentPosition(positionInfo);

        // 获取分数段分布
        List<Map<String, Object>> scoreDistribution = examScoreMapper.selectGradeScoreDistribution(examId);
        List<StudentDashboardRespVO.ScoreRangeInfo> scoreRanges = new ArrayList<>();

        for (Map<String, Object> range : scoreDistribution) {
            StudentDashboardRespVO.ScoreRangeInfo rangeInfo = new StudentDashboardRespVO.ScoreRangeInfo();
            rangeInfo.setScoreRange((String) range.get("scoreRange"));
            rangeInfo.setCount(((Number) range.get("count")).intValue());

            if (gradeTotalCount != null && gradeTotalCount > 0) {
                double percentageValue = 100.0 * rangeInfo.getCount() / gradeTotalCount;
                if (!Double.isNaN(percentageValue) && !Double.isInfinite(percentageValue)) {
                    BigDecimal percentage = BigDecimal.valueOf(percentageValue)
                            .setScale(1, RoundingMode.HALF_UP);
                    rangeInfo.setPercentage(percentage);
                }
            }

            // 判断是否包含当前学生
            rangeInfo.setIncludesStudent(isScoreInRange(examScore.getTotalScore(), rangeInfo.getScoreRange()));

            scoreRanges.add(rangeInfo);
        }
        distributionInfo.setScoreRanges(scoreRanges);

        // 设置年级统计信息
        StudentDashboardRespVO.GradeStatistics gradeStatistics = new StudentDashboardRespVO.GradeStatistics();
        gradeStatistics.setTotalStudents(gradeTotalCount);
        if (gradeStats.get("maxScore") != null) {
            gradeStatistics.setMaxScore((BigDecimal) gradeStats.get("maxScore"));
        }
        if (gradeStats.get("minScore") != null) {
            gradeStatistics.setMinScore((BigDecimal) gradeStats.get("minScore"));
        }
        if (gradeStats.get("avgScore") != null) {
            gradeStatistics.setAvgScore((BigDecimal) gradeStats.get("avgScore"));
        }
        if (gradeStats.get("standardDeviation") != null) {
            Double stdDev = (Double) gradeStats.get("standardDeviation");
            if (!Double.isNaN(stdDev) && !Double.isInfinite(stdDev)) {
                gradeStatistics.setStandardDeviation(BigDecimal.valueOf(stdDev));
            }
        }
        distributionInfo.setGradeStats(gradeStatistics);

        return distributionInfo;
    }

    /**
     * 判断分数是否在指定范围内
     */
    private boolean isScoreInRange(BigDecimal score, String scoreRange) {
        if (score == null || scoreRange == null) {
            return false;
        }

        try {
            if (scoreRange.contains("-")) {
                String[] parts = scoreRange.split("-");
                if (parts.length == 2) {
                    BigDecimal min = new BigDecimal(parts[0]);
                    BigDecimal max = new BigDecimal(parts[1]);
                    return score.compareTo(min) >= 0 && score.compareTo(max) <= 0;
                }
            } else if (scoreRange.contains("以下")) {
                String numStr = scoreRange.replace("以下", "");
                BigDecimal threshold = new BigDecimal(numStr);
                return score.compareTo(threshold) < 0;
            } else if (scoreRange.contains("以上")) {
                String numStr = scoreRange.replace("以上", "");
                BigDecimal threshold = new BigDecimal(numStr);
                return score.compareTo(threshold) >= 0;
            }
        } catch (NumberFormatException e) {
            log.warn("解析分数范围失败: {}", scoreRange, e);
        }

        return false;
    }

    /**
     * 获取考试对比信息
     */
    private List<StudentDashboardRespVO.ExamComparisonInfo> getExamComparisonInfo(Long studentId, List<Long> examIds) {
        List<StudentDashboardRespVO.ExamComparisonInfo> comparisons = new ArrayList<>();

        for (Long examId : examIds) {
            ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(examId, studentId);
            ExamTestDO examTest = examTestMapper.selectById(examId);

            if (examScore != null && examTest != null) {
                StudentDashboardRespVO.ExamComparisonInfo comparison = new StudentDashboardRespVO.ExamComparisonInfo();
                comparison.setExamId(examId);
                comparison.setExamName(examTest.getExamName());
                comparison.setExamDate(examTest.getExamDate());
                comparison.setTotalScore(examScore.getTotalScore());
                comparison.setClassRank(examScore.getClassRank());
                comparison.setGradeRank(examScore.getGradeRank());

                // 设置各科成绩对比
                Map<String, StudentDashboardRespVO.SubjectComparisonInfo> subjectComparisons = new HashMap<>();
                addSubjectComparison(subjectComparisons, "语文", examScore.getChineseScore());
                addSubjectComparison(subjectComparisons, "数学", examScore.getMathScore());
                addSubjectComparison(subjectComparisons, "英语", examScore.getEnglishScore());
                addSubjectComparison(subjectComparisons, "物理", examScore.getPhysicsScore());
                addSubjectComparison(subjectComparisons, "化学", examScore.getChemistryScore());
                addSubjectComparison(subjectComparisons, "生物", examScore.getBiologyScore());
                addSubjectComparison(subjectComparisons, "政治", examScore.getPoliticsScore());
                addSubjectComparison(subjectComparisons, "历史", examScore.getHistoryScore());
                addSubjectComparison(subjectComparisons, "地理", examScore.getGeographyScore());
                comparison.setSubjectComparisons(subjectComparisons);
                
                // 设置新增字段
                comparison.setTotalScoreAssigned(examScore.getTotalScoreAssigned());
                comparison.setTotalUnionRank(examScore.getTotalUnionRank());
                comparison.setCombinationRank(examScore.getCombinationRank());
                comparison.setSchoolRank(examScore.getSchoolRank());
                comparison.setSubjectCombination(examScore.getSubjectCombination());

                comparisons.add(comparison);
            }
        }

        // 计算与上次考试的差异
        for (int i = 0; i < comparisons.size() - 1; i++) {
            StudentDashboardRespVO.ExamComparisonInfo current = comparisons.get(i);
            StudentDashboardRespVO.ExamComparisonInfo previous = comparisons.get(i + 1);

            if (current.getTotalScore() != null && previous.getTotalScore() != null) {
                current.setScoreDifference(current.getTotalScore().subtract(previous.getTotalScore()));
            }

            if (current.getGradeRank() != null && previous.getGradeRank() != null) {
                current.setRankChange(previous.getGradeRank() - current.getGradeRank()); // 排名下降为正值
            }
        }

        return comparisons;
    }

    /**
     * 添加科目对比信息
     */
    private void addSubjectComparison(Map<String, StudentDashboardRespVO.SubjectComparisonInfo> subjectComparisons,
                                     String subjectName, BigDecimal score) {
        if (score != null) {
            StudentDashboardRespVO.SubjectComparisonInfo comparison = new StudentDashboardRespVO.SubjectComparisonInfo();
            comparison.setSubjectName(subjectName);
            comparison.setCurrentScore(score);
            // 其他字段在后续处理中设置
            subjectComparisons.put(subjectName, comparison);
        }
    }

    // 以下是其他辅助方法的简化实现，实际项目中需要完善

    private StudentRankingRespVO.ClassRankingInfo getClassRankingInfo(Long examId, Long studentId) {
        // 简化实现，实际需要完善
        return new StudentRankingRespVO.ClassRankingInfo();
    }

    private StudentRankingRespVO.GradeRankingInfo getGradeRankingInfo(Long examId, Long studentId) {
        // 简化实现，实际需要完善
        return new StudentRankingRespVO.GradeRankingInfo();
    }

    private List<StudentRankingRespVO.SubjectRankingInfo> getSubjectRankingList(Long examId, Long studentId, String subjectName) {
        // 简化实现，实际需要完善
        return new ArrayList<>();
    }

    private StudentExamComparisonRespVO.StudentBasicInfo getStudentBasicInfoForComparison(Long studentId) {
        // 简化实现，实际需要完善
        return new StudentExamComparisonRespVO.StudentBasicInfo();
    }

    private List<StudentExamComparisonRespVO.ExamComparisonData> getExamComparisonData(Long studentId, List<Long> examIds) {
        // 简化实现，实际需要完善
        return new ArrayList<>();
    }

    private StudentExamComparisonRespVO.TrendAnalysisInfo calculateTotalScoreTrend(List<StudentExamComparisonRespVO.ExamComparisonData> examComparisons) {
        // 简化实现，实际需要完善
        return new StudentExamComparisonRespVO.TrendAnalysisInfo();
    }

    private Map<String, StudentExamComparisonRespVO.TrendAnalysisInfo> calculateSubjectTrends(List<StudentExamComparisonRespVO.ExamComparisonData> examComparisons) {
        // 简化实现，实际需要完善
        return new HashMap<>();
    }

    private StudentExamComparisonRespVO.RankingTrendInfo calculateRankingTrend(List<StudentExamComparisonRespVO.ExamComparisonData> examComparisons) {
        // 简化实现，实际需要完善
        return new StudentExamComparisonRespVO.RankingTrendInfo();
    }

    private StudentExamComparisonRespVO.ProgressAnalysisInfo calculateProgressAnalysis(List<StudentExamComparisonRespVO.ExamComparisonData> examComparisons) {
        // TODO: 实现进步分析逻辑
        return new StudentExamComparisonRespVO.ProgressAnalysisInfo();
    }

    @Override
    public StudentDashboardRespVO.EquivalentScoreRankInfo getStudentEquivalentScoreRank(Long studentId, Long examId, Long controlLineId) {
        log.info("获取学生等效位次和等效分信息：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId);
        
        try {
            // 获取等效位次和等效分记录
            cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreRankDO equivalentScoreRank = 
                    equivalentScoreRankService.getEquivalentScoreRank(examId, studentId, controlLineId);
            
            if (equivalentScoreRank == null) {
                log.warn("未找到等效位次和等效分记录，尝试计算：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId);
                return calculateStudentEquivalentScoreRank(studentId, examId, controlLineId);
            }
            
            return convertToEquivalentScoreRankInfo(equivalentScoreRank);
            
        } catch (Exception e) {
            log.error("获取学生等效位次和等效分信息失败：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId, e);
            return null;
        }
    }

    @Override
    public StudentDashboardRespVO.EquivalentScoreRankInfo calculateStudentEquivalentScoreRank(Long studentId, Long examId, Long controlLineId) {
        log.info("计算学生等效位次和等效分：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId);
        
        try {
            // 调用等效位次和等效分服务进行计算
            cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreRankDO result = 
                    equivalentScoreRankService.calculateEquivalentScoreRank(examId, studentId, controlLineId);
            
            if (result == null) {
                log.warn("等效位次和等效分计算失败：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId);
                return null;
            }
            
            return convertToEquivalentScoreRankInfo(result);
            
        } catch (Exception e) {
            log.error("计算学生等效位次和等效分失败：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId, e);
            return null;
        }
    }

    @Override
    public StudentDashboardRespVO.EquivalentRankTrendInfo getEquivalentRankTrend(Long studentId, Long examId, Long controlLineId) {
        log.info("获取学生等效位次趋势分析：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId);
        
        try {
            // 获取等效位次和等效分记录
            cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreRankDO equivalentScoreRank = 
                    equivalentScoreRankService.getEquivalentScoreRank(examId, studentId, controlLineId);
            
            if (equivalentScoreRank == null) {
                log.warn("未找到等效位次和等效分记录：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId);
                return null;
            }
            
            return calculateEquivalentRankTrend(equivalentScoreRank);
            
        } catch (Exception e) {
            log.error("获取学生等效位次趋势分析失败：studentId={}, examId={}, controlLineId={}", studentId, examId, controlLineId, e);
            return null;
        }
    }

    @Override
    public StudentDashboardRespVO.EquivalentScoreRankInfo getStudentEquivalentScoreRankByExam(Long studentId, Long examId) {
        log.info("根据考试ID获取学生等效位次和等效分信息，学生ID: {}, 考试ID: {}", studentId, examId);
        
        // 根据考试ID获取特控线ID
        Long controlLineId = getControlLineIdByExamId(examId);
        if (controlLineId == null) {
            log.warn("未找到考试ID为{}的特控线配置", examId);
            return null;
        }
        
        return getStudentEquivalentScoreRank(studentId, examId, controlLineId);
    }

    @Override
    public StudentDashboardRespVO.EquivalentScoreRankInfo calculateStudentEquivalentScoreRankByExam(Long studentId, Long examId) {
        log.info("根据考试ID计算学生等效位次和等效分，学生ID: {}, 考试ID: {}", studentId, examId);
        
        // 根据考试ID获取特控线ID
        Long controlLineId = getControlLineIdByExamId(examId);
        if (controlLineId == null) {
            log.warn("未找到考试ID为{}的特控线配置", examId);
            return null;
        }
        
        return calculateStudentEquivalentScoreRank(studentId, examId, controlLineId);
    }

    @Override
    public StudentDashboardRespVO.EquivalentRankTrendInfo getEquivalentRankTrendByExam(Long studentId, Long examId) {
        log.info("根据考试ID获取学生等效位次趋势分析，学生ID: {}, 考试ID: {}", studentId, examId);
        
        // 根据考试ID获取特控线ID
        Long controlLineId = getControlLineIdByExamId(examId);
        if (controlLineId == null) {
            log.warn("未找到考试ID为{}的特控线配置", examId);
            return null;
        }
        
        return getEquivalentRankTrend(studentId, examId, controlLineId);
    }
    
    /**
     * 转换等效位次和等效分DO为VO
     */
    private StudentDashboardRespVO.EquivalentScoreRankInfo convertToEquivalentScoreRankInfo(
            cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreRankDO equivalentScoreRank) {
        
        if (equivalentScoreRank == null) {
            return null;
        }
        
        StudentDashboardRespVO.EquivalentScoreRankInfo info = new StudentDashboardRespVO.EquivalentScoreRankInfo();
        info.setOriginalScore(equivalentScoreRank.getOriginalScore());
        info.setControlLineScore(equivalentScoreRank.getControlLineScore());
        info.setProvince(equivalentScoreRank.getProvince());
        info.setExamType(equivalentScoreRank.getExamType());
        info.setScoreDifference(equivalentScoreRank.getScoreDifference());
        
        // 设置三年等效分数据（从详情列表中获取）
        if (equivalentScoreRank.getScoreDetails() != null) {
            for (cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreDetailDO detail : equivalentScoreRank.getScoreDetails()) {
                switch (detail.getYear()) {
                    case 2023:
                        info.setEquivalentScore2023(detail.getEquivalentScore());
                        info.setEquivalentRank2023(detail.getEquivalentRank());
                        info.setProvinceControlLine2023(detail.getProvinceControlLine());
                        break;
                    case 2024:
                        info.setEquivalentScore2024(detail.getEquivalentScore());
                        info.setEquivalentRank2024(detail.getEquivalentRank());
                        info.setProvinceControlLine2024(detail.getProvinceControlLine());
                        break;
                    case 2025:
                        info.setEquivalentScore2025(detail.getEquivalentScore());
                        info.setEquivalentRank2025(detail.getEquivalentRank());
                        info.setProvinceControlLine2025(detail.getProvinceControlLine());
                        break;
                }
            }
        }
        
        // 设置计算相关信息
        info.setCalculationDate(equivalentScoreRank.getCalculationDate());
        info.setCalculationStatus(equivalentScoreRank.getCalculationStatus());
        info.setErrorMessage(equivalentScoreRank.getErrorMessage());
        
        // 获取特控线名称
        try {
            cn.iocoder.yudao.module.system.dal.dataobject.examcontrolline.ExamControlLineDO controlLine = 
                    examControlLineService.getExamControlLine(equivalentScoreRank.getControlLineId());
            if (controlLine != null) {
                info.setControlLineName(controlLine.getLineName());
            }
        } catch (Exception e) {
            log.warn("获取特控线名称失败：controlLineId={}", equivalentScoreRank.getControlLineId(), e);
        }
        
        // 计算趋势分析
        info.setRankTrend(calculateEquivalentRankTrend(equivalentScoreRank));
        
        return info;
    }
    
    /**
     * 计算等效位次趋势分析
     */
    private StudentDashboardRespVO.EquivalentRankTrendInfo calculateEquivalentRankTrend(
            cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreRankDO equivalentScoreRank) {
        
        if (equivalentScoreRank == null) {
            return null;
        }
        
        StudentDashboardRespVO.EquivalentRankTrendInfo trendInfo = new StudentDashboardRespVO.EquivalentRankTrendInfo();
        
        // 收集三年的位次数据（从详情列表中获取）
        List<Integer> ranks = new ArrayList<>();
        if (equivalentScoreRank.getScoreDetails() != null) {
            for (cn.iocoder.yudao.module.system.dal.dataobject.equivalentscorerank.EquivalentScoreDetailDO detail : equivalentScoreRank.getScoreDetails()) {
                if (detail.getEquivalentRank() != null) {
                    ranks.add(detail.getEquivalentRank());
                }
            }
        }
        
        if (ranks.isEmpty()) {
            return trendInfo;
        }
        
        // 计算基本统计信息
        Integer bestRank = Collections.min(ranks); // 位次越小越好
        Integer worstRank = Collections.max(ranks);
        Integer averageRank = (int) ranks.stream().mapToInt(Integer::intValue).average().orElse(0);
        
        trendInfo.setBestRank(bestRank);
        trendInfo.setWorstRank(worstRank);
        trendInfo.setAverageRank(averageRank);
        
        // 计算改善幅度（最差位次 - 最好位次）
        Integer improvementRange = worstRank - bestRank;
        trendInfo.setImprovementRange(improvementRange);
        
        // 分析趋势方向
        String trendDirection = "STABLE";
        String trendDescription = "等效位次保持稳定";
        
        if (ranks.size() >= 2) {
            Integer firstRank = ranks.get(0);
            Integer lastRank = ranks.get(ranks.size() - 1);
            
            if (lastRank < firstRank) {
                trendDirection = "IMPROVING";
                trendDescription = "等效位次呈现上升趋势，表现优秀";
            } else if (lastRank > firstRank) {
                trendDirection = "DECLINING";
                trendDescription = "等效位次有所下降，需要加强努力";
            }
        }
        
        trendInfo.setTrendDirection(trendDirection);
        trendInfo.setTrendDescription(trendDescription);
        
        // 计算稳定性评分（基于位次变化的标准差）
        BigDecimal stabilityScore = calculateStabilityScore(ranks);
        trendInfo.setStabilityScore(stabilityScore);
        
        return trendInfo;
    }
    
    /**
     * 计算稳定性评分
     */
    private BigDecimal calculateStabilityScore(List<Integer> ranks) {
        if (ranks.size() < 2) {
            return BigDecimal.valueOf(100); // 只有一个数据点，认为完全稳定
        }
        
        // 计算平均值
        double average = ranks.stream().mapToInt(Integer::intValue).average().orElse(0);
        
        // 计算标准差
        double variance = ranks.stream()
                .mapToDouble(rank -> Math.pow(rank - average, 2))
                .average()
                .orElse(0);
        double standardDeviation = Math.sqrt(variance);
        
        // 计算变异系数（标准差/平均值）
        double coefficientOfVariation = average > 0 ? standardDeviation / average : 0;
        
        // 稳定性评分：100 - (变异系数 * 100)，最小为0
        double stabilityScore = Math.max(0, 100 - (coefficientOfVariation * 100));
        
        return BigDecimal.valueOf(stabilityScore).setScale(1, RoundingMode.HALF_UP);
    }
    
    /**
     * 获取学生的最高分记录信息
     */
    private List<StudentDashboardRespVO.TopScoreRecordInfo> getTopScoreRecords(Long studentId, Long examId) {
        try {
            // 查询学生在指定考试中的最高分记录
             List<cn.iocoder.yudao.module.system.dal.dataobject.topscorerecord.TopScoreRecordDO> topScoreRecords = 
                 topScoreRecordMapper.selectList(examId, studentId, null);
            
            if (CollUtil.isEmpty(topScoreRecords)) {
                return new ArrayList<>();
            }
            
            // 转换为VO
            List<StudentDashboardRespVO.TopScoreRecordInfo> result = new ArrayList<>();
            for (cn.iocoder.yudao.module.system.dal.dataobject.topscorerecord.TopScoreRecordDO record : topScoreRecords) {
                StudentDashboardRespVO.TopScoreRecordInfo info = new StudentDashboardRespVO.TopScoreRecordInfo();
                info.setId(record.getId());
                info.setExamId(record.getExamId());
                info.setStudentId(record.getStudentId());
                info.setRank(record.getRank());
                info.setSubjectName(record.getSubjectName());
                info.setOriginalScore(record.getOriginalScore());
                info.setAssignedScore(record.getAssignedScore());
                info.setUnionRank(record.getUnionRank());
                info.setSchoolRank(record.getSchoolRank());
                info.setClassRank(record.getClassRank());
                info.setRemark(record.getRemark());
                info.setCreateTime(record.getCreateTime());
                result.add(info);
            }
            
            // 按排名排序
            result.sort(Comparator.comparing(StudentDashboardRespVO.TopScoreRecordInfo::getRank, 
                Comparator.nullsLast(Comparator.naturalOrder())));
            
            return result;
            
        } catch (Exception e) {
            log.warn("获取学生{}在考试{}的最高分记录失败: {}", studentId, examId, e.getMessage());
            return new ArrayList<>();
        }
    }
    
    /**
     * 使用省控线进行等效位次计算
     * 当系统中没有设置考试的特控线时，使用省控线作为特控线进行计算
     */
    private StudentDashboardRespVO.EquivalentScoreRankInfo getStudentEquivalentScoreRankWithProvinceControlLine(Long studentId, Long examId) {
        try {
            // 获取学生成绩
            ExamScoreDO examScore = examScoreMapper.selectByExamIdAndStudentId(examId, studentId);
            if (examScore == null) {
                log.warn("未找到学生成绩，studentId: {}, examId: {}", studentId, examId);
                return null;
            }
            
            // 获取学生省份信息
            String province = examScore.getProvince();
            if (province == null || province.trim().isEmpty()) {
                log.warn("学生成绩中未设置省份信息，无法使用省控线计算等效位次，studentId: {}, examId: {}", studentId, examId);
                return null;
            }
            
            // 确定考试类型（物理类/历史类）
            String examType = determineExamTypeFromScore(examScore);
            if (examType == null) {
                log.warn("无法确定考试类型，studentId: {}, examId: {}", studentId, examId);
                return null;
            }
            
            // 获取当前年份的省控线
            Integer currentYear = LocalDateTime.now().getYear();
            List<cn.iocoder.yudao.module.system.dal.dataobject.gugu.ProvinceScoreDO> provinceScores = 
                    provinceScoreService.getProvinceScoreList(province, currentYear, examType);
            
            // 查找特殊类型招生控制线（相当于特控线）
            cn.iocoder.yudao.module.system.dal.dataobject.gugu.ProvinceScoreDO provinceControlLine = provinceScores.stream()
                    .filter(score -> "特殊类型招生控制线".equals(score.getScoreBatch()) || "特殊".equals(score.getScoreBatch()))
                    .findFirst()
                    .orElse(null);
            
            if (provinceControlLine == null) {
                log.warn("未找到{}省{}年{}的特殊类型招生控制线，无法计算等效位次", province, currentYear, examType);
                return null;
            }
            
            // 构建等效位次信息
            StudentDashboardRespVO.EquivalentScoreRankInfo equivalentInfo = new StudentDashboardRespVO.EquivalentScoreRankInfo();
            // 优先使用赋分总分，如果为空则使用原始总分
            BigDecimal originalScore = ObjectUtil.defaultIfNull(examScore.getTotalScoreAssigned(), examScore.getTotalScore());
            equivalentInfo.setOriginalScore(originalScore);
            equivalentInfo.setControlLineScore(BigDecimal.valueOf(provinceControlLine.getScore()));
            equivalentInfo.setControlLineName("省控线（" + provinceControlLine.getScoreBatch() + "）");
            equivalentInfo.setProvince(province);
            equivalentInfo.setExamType(examType);
            
            // 计算与省控线的差值
            if (originalScore != null) {
                BigDecimal scoreDifference = originalScore.subtract(BigDecimal.valueOf(provinceControlLine.getScore()));
                equivalentInfo.setScoreDifference(scoreDifference);
            }
            
            // 设置计算时间和状态
            equivalentInfo.setCalculationDate(LocalDateTime.now());
            equivalentInfo.setCalculationStatus(1); // 1表示成功
            
            // 获取多年省控线数据进行等效分计算
            List<Integer> years = Arrays.asList(2023, 2024, 2025);
            Map<Integer, BigDecimal> provinceControlLines = new HashMap<>();
            
            for (Integer year : years) {
                List<cn.iocoder.yudao.module.system.dal.dataobject.gugu.ProvinceScoreDO> yearScores = 
                        provinceScoreService.getProvinceScoreList(province, year, examType);
                
                cn.iocoder.yudao.module.system.dal.dataobject.gugu.ProvinceScoreDO yearControlLine = yearScores.stream()
                        .filter(score -> "特殊类型招生控制线".equals(score.getScoreBatch()) || "特殊".equals(score.getScoreBatch()))
                        .findFirst()
                        .orElse(null);
                
                if (yearControlLine != null) {
                    provinceControlLines.put(year, BigDecimal.valueOf(yearControlLine.getScore()));
                }
            }
            
            // 设置各年份的省控线
            if (provinceControlLines.containsKey(2023)) {
                equivalentInfo.setProvinceControlLine2023(provinceControlLines.get(2023));
            }
            if (provinceControlLines.containsKey(2024)) {
                equivalentInfo.setProvinceControlLine2024(provinceControlLines.get(2024));
            }
            if (provinceControlLines.containsKey(2025)) {
                equivalentInfo.setProvinceControlLine2025(provinceControlLines.get(2025));
            }
            
            // 简化的等效分计算（基于与省控线的差值）
            if (equivalentInfo.getScoreDifference() != null) {
                for (Map.Entry<Integer, BigDecimal> entry : provinceControlLines.entrySet()) {
                    BigDecimal equivalentScore = entry.getValue().add(equivalentInfo.getScoreDifference());
                    
                    switch (entry.getKey()) {
                        case 2023:
                            equivalentInfo.setEquivalentScore2023(equivalentScore);
                            break;
                        case 2024:
                            equivalentInfo.setEquivalentScore2024(equivalentScore);
                            break;
                        case 2025:
                            equivalentInfo.setEquivalentScore2025(equivalentScore);
                            break;
                    }
                }
            }
            
            // 计算等效位次（基于等效分的简化估算）
            // 注意：这是一个简化的计算方法，实际的等效位次需要更复杂的算法
            // 每个年份根据其对应的省控线和等效分独立计算位次
            
            // 2023年等效位次计算
            if (equivalentInfo.getEquivalentScore2023() != null && provinceControlLines.containsKey(2023)) {
                BigDecimal score2023 = equivalentInfo.getEquivalentScore2023();
                BigDecimal controlLine2023 = provinceControlLines.get(2023);
                int rank2023 = calculateEquivalentRank(score2023, controlLine2023, 2023);
                equivalentInfo.setEquivalentRank2023(rank2023);
            }
            
            // 2024年等效位次计算
            if (equivalentInfo.getEquivalentScore2024() != null && provinceControlLines.containsKey(2024)) {
                BigDecimal score2024 = equivalentInfo.getEquivalentScore2024();
                BigDecimal controlLine2024 = provinceControlLines.get(2024);
                int rank2024 = calculateEquivalentRank(score2024, controlLine2024, 2024);
                equivalentInfo.setEquivalentRank2024(rank2024);
            }
            
            // 2025年等效位次计算
            if (equivalentInfo.getEquivalentScore2025() != null && provinceControlLines.containsKey(2025)) {
                BigDecimal score2025 = equivalentInfo.getEquivalentScore2025();
                BigDecimal controlLine2025 = provinceControlLines.get(2025);
                int rank2025 = calculateEquivalentRank(score2025, controlLine2025, 2025);
                equivalentInfo.setEquivalentRank2025(rank2025);
            }
            
            log.info("使用省控线成功计算等效位次，studentId: {}, examId: {}, province: {}, examType: {}, controlLineScore: {}", 
                    studentId, examId, province, examType, provinceControlLine.getScore());
            
            return equivalentInfo;
            
        } catch (Exception e) {
            log.error("使用省控线计算等效位次失败，studentId: {}, examId: {}", studentId, examId, e);
            return null;
        }
    }
    
    /**
     * 计算等效位次
     * 根据等效分、省控线和年份计算对应的等效位次
     * 
     * @param equivalentScore 等效分
     * @param controlLineScore 省控线分数
     * @param year 年份
     * @return 等效位次
     */
    private int calculateEquivalentRank(BigDecimal equivalentScore, BigDecimal controlLineScore, Integer year) {
        // 计算与省控线的分数差值
        BigDecimal scoreDifference = equivalentScore.subtract(controlLineScore);
        
        // 不同年份的基准位次（特控线对应的大概位次）
        int baseRank;
        double rankPerScore = switch (year) {
            case 2023 -> {
                baseRank = 48000; // 2023年特控线对应约4.8万位次
                yield 750;
            }
            case 2024 -> {
                baseRank = 52000; // 2024年特控线对应约5.2万位次
                yield 820;
            }
            case 2025 -> {
                baseRank = 55000; // 2025年特控线对应约5.5万位次（预估）
                yield 880;
            }
            default -> {
                baseRank = 50000; // 默认5万位次
                yield 800;
            }
        }; // 每分对应的位次数

        // 计算位次变化（分数越高，位次越小）
        int rankChange = (int) (scoreDifference.doubleValue() * (-rankPerScore));
        
        // 计算最终位次
        int estimatedRank = baseRank + rankChange;
        
        // 确保位次不小于1，不大于合理上限
        estimatedRank = Math.max(1, estimatedRank);
        estimatedRank = Math.min(500000, estimatedRank); // 最大不超过50万位次
        
        return estimatedRank;
    }
    
    /**
     * 根据学生成绩确定考试类型
     */
    private String determineExamTypeFromScore(ExamScoreDO examScore) {
        // 根据首选科目判断
        if ("物理".equals(examScore.getFirstSubject())) {
            return "物理类";
        } else if ("历史".equals(examScore.getFirstSubject())) {
            return "历史类";
        }
        
        // 根据科目组合判断
        String subjectCombination = examScore.getSubjectCombination();
        if (subjectCombination != null) {
            if (subjectCombination.contains("物理")) {
                return "物理类";
            } else if (subjectCombination.contains("历史")) {
                return "历史类";
            }
        }
        
        // 根据具体科目成绩判断
        if (examScore.getPhysicsScore() != null && examScore.getPhysicsScore().compareTo(BigDecimal.ZERO) > 0) {
            return "物理类";
        } else if (examScore.getHistoryScore() != null && examScore.getHistoryScore().compareTo(BigDecimal.ZERO) > 0) {
            return "历史类";
        }
        
        // 默认返回物理类
        return "物理类";
    }
    
    /**
     * 获取学生参与的所有考试列表
     */
    private List<StudentDashboardRespVO.StudentExamInfo> getStudentExamList(Long studentId) {
        try {
            // 查询学生的所有考试成绩记录
            List<ExamScoreDO> examScores = examScoreMapper.selectList(new LambdaQueryWrapperX<ExamScoreDO>()
                    .eq(ExamScoreDO::getStudentId, studentId)
                    .orderByDesc(ExamScoreDO::getCreateTime));
            
            if (CollUtil.isEmpty(examScores)) {
                return new ArrayList<>();
            }
            
            List<StudentDashboardRespVO.StudentExamInfo> studentExams = new ArrayList<>();
            
            for (ExamScoreDO examScore : examScores) {
                try {
                    // 获取考试信息
                    ExamTestDO examTest = examTestMapper.selectById(examScore.getExamId());
                    if (examTest == null) {
                        continue;
                    }
                    
                    // 获取班级信息
                    ExamClassDO examClass = null;
                    if (CollUtil.isNotEmpty(examTest.getClassIds())) {
                        // 取第一个班级ID作为主要班级
                        examClass = examClassMapper.selectById(examTest.getClassIds().get(0));
                    }
                    
                    StudentDashboardRespVO.StudentExamInfo examInfo = new StudentDashboardRespVO.StudentExamInfo();
                    
                    // 设置考试基本信息
                    examInfo.setExamId(examTest.getId());
                    examInfo.setExamName(examTest.getExamName());
                    examInfo.setExamType(examTest.getExamType());
                    examInfo.setExamDate(examTest.getExamDate());
                    examInfo.setExamStatus("已完成"); // 有成绩记录说明考试已完成
                    examInfo.setHasScore(true);
                    examInfo.setCreateTime(examTest.getCreateTime());
                    
                    // 设置成绩信息
                    examInfo.setTotalScore(examScore.getTotalScore());
                    examInfo.setFullScore(examTest.getTotalScore()); // 使用考试的总分作为满分
                    
                    // 设置排名信息
                    examInfo.setClassRank(examScore.getClassRank());
                    examInfo.setGradeRank(examScore.getGradeRank());
                    examInfo.setSchoolRank(examScore.getSchoolRank());
                    examInfo.setUnionRank(examScore.getTotalUnionRank());
                    examInfo.setCombinationRank(examScore.getCombinationRank());
                    
                    // 设置其他信息
                    examInfo.setSubjectCombination(examScore.getSubjectCombination());
                    examInfo.setProvince(examScore.getProvince());
                    
                    // 设置班级信息
                    if (examClass != null) {
                        examInfo.setClassId(examClass.getId());
                        examInfo.setClassName(examClass.getClassName());
                    }
                    
                    studentExams.add(examInfo);
                    
                } catch (Exception e) {
                    log.warn("处理考试记录失败，examId: {}, studentId: {}, error: {}", 
                            examScore.getExamId(), studentId, e.getMessage());
                }
            }
            
            // 按考试时间倒序排列（最新的考试在前）
            studentExams.sort((a, b) -> {
                if (a.getExamDate() == null && b.getExamDate() == null) {
                    return 0;
                }
                if (a.getExamDate() == null) {
                    return 1;
                }
                if (b.getExamDate() == null) {
                    return -1;
                }
                return b.getExamDate().compareTo(a.getExamDate());
            });
            
            log.info("成功获取学生考试列表，studentId: {}, 考试数量: {}", studentId, studentExams.size());
            return studentExams;
            
        } catch (Exception e) {
            log.error("获取学生考试列表失败，studentId: {}", studentId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取目标分析信息
     */
    private List<StudentDashboardRespVO.GoalAnalysisInfo> getGoalAnalysis(Long studentId, StudentDashboardRespVO.EquivalentScoreRankInfo equivalentInfo) {
        // 获取学生目标
        List<StudentMajorGroupGoalDO> goals = studentMajorGroupGoalService.getMajorGroupGoalList(studentId);
        if (CollUtil.isEmpty(goals)) {
            return Collections.emptyList();
        }

        List<StudentDashboardRespVO.GoalAnalysisInfo> result = new ArrayList<>();
        
        // 获取等效分和等效位次
        BigDecimal myScore = equivalentInfo != null ? equivalentInfo.getEquivalentScore2024() : null; // 优先使用2024年的等效分
        if (myScore == null && equivalentInfo != null) {
            myScore = equivalentInfo.getEquivalentScore2025(); // 如果没有特定年份的，使用通用的
        }
        
        Integer myRank = equivalentInfo != null ? equivalentInfo.getEquivalentRank2024() : null;
         if (myRank == null && equivalentInfo != null) {
            myRank = equivalentInfo.getEquivalentRank2025();
        }

        for (StudentMajorGroupGoalDO goal : goals) {
            StudentDashboardRespVO.GoalAnalysisInfo info = new StudentDashboardRespVO.GoalAnalysisInfo();
            info.setId(goal.getId());
            info.setUniversityName(goal.getUniversityName());
            info.setMajorGroupName(goal.getMajorGroupName());
            info.setUniversityMajorGroup(goal.getRecruitCode()); 
            info.setYear(goal.getYear());
            info.setMinScore(goal.getMinScore());
            info.setMinRank(goal.getMinRank());
            info.setMyEquivalentScore(myScore);
            info.setMyEquivalentRank(myRank);

            // 计算差距和概率
            if (myScore != null && goal.getMinScore() != null) {
                BigDecimal scoreGap = myScore.subtract(new BigDecimal(goal.getMinScore()));
                info.setScoreGap(scoreGap);
                
                // 简单的概率判断逻辑
                if (scoreGap.compareTo(new BigDecimal("10")) >= 0) {
                    info.setProbability("保");
                } else if (scoreGap.compareTo(BigDecimal.ZERO) >= 0) {
                    info.setProbability("稳");
                } else if (scoreGap.compareTo(new BigDecimal("-20")) >= 0) {
                    info.setProbability("冲");
                } else {
                    info.setProbability("难");
                }
            }
            
            if (myRank != null && goal.getMinRank() != null) {
                int rankGap = myRank - goal.getMinRank();
                info.setRankGap(rankGap);
            }

            result.add(info);
        }
        
        return result;
    }
}
